﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
public class ExportUtil {

    public static string TAG = "Asset Export Tool";

    public static readonly string ASSETSBUNDLE_PATH = Application.streamingAssetsPath + "/assetsbundle/";

    [MenuItem ("Assets/Export To AssetsBundles/Each File One Package")]
    public static void ExportToAssetBundle () {
        Object[] selectedObjects = Selection.GetFiltered (typeof (GameObject), SelectionMode.Assets);

        if (!Directory.Exists (ASSETSBUNDLE_PATH)) {
            Directory.CreateDirectory (ASSETSBUNDLE_PATH);
        }

        foreach (Object obj in selectedObjects) {
            string fullPath = AssetDatabase.GetAssetPath (obj.GetInstanceID ()).Replace ('\\', '/');
            string fullName = fullPath.Substring (fullPath.LastIndexOf ("/") + 1);
            string fileName = fullName.Substring (0, fullName.LastIndexOf ("."));
            string abPath = ASSETSBUNDLE_PATH + fileName;

            Debug.Log ("Building ab" + abPath);
#if UNITY_ANDROID || UNITY_IPHONE
            BuildPipeline.BuildAssetBundle (obj, null, abPath + "_a.ab", BuildAssetBundleOptions.CollectDependencies, BuildTarget.Android);
            BuildPipeline.BuildAssetBundle (obj, null, abPath + "_i.ab", BuildAssetBundleOptions.CollectDependencies, BuildTarget.iOS);
#else
            BuildPipeline.BuildAssetBundle (obj, null, abPath, BuildAssetBundleOptions.CollectDependencies, BuildTarget.StandaloneWindows);
#endif
            List<string> mapping = new List<string> ();
            foreach (Object o in selectedObjects) {
                mapping.Add (fileName + "=" + o.name);
            }
            outputMappingFile (mapping);
        }
    }

    [MenuItem ("Assets/Export To AssetsBundles/One Package")]
    public static void ExportToAssetbundleOnePack () {
        Object[] selectedObjects = Selection.GetFiltered (typeof (GameObject), SelectionMode.Assets);

        Object mainAsset = selectedObjects[0];
        string[] data = AssetDatabase.GetAssetPath (mainAsset).Split ('/');
        string dirName = data[data.Length - 2];

        string abPath = ASSETSBUNDLE_PATH + dirName;

        if (!Directory.Exists (ASSETSBUNDLE_PATH)) {
            Directory.CreateDirectory (ASSETSBUNDLE_PATH);
        }

        LogUtil.Log (TAG, "Building ab" + abPath);

        foreach (Object o in selectedObjects) {
            LogUtil.Log (TAG, "including " + AssetDatabase.GetAssetPath (o.GetInstanceID ()));
        }
#if UNITY_ANDROID || UNITY_IPHONE
        BuildPipeline.BuildAssetBundle (mainAsset, selectedObjects, abPath + "_a.ab", BuildAssetBundleOptions.CollectDependencies, BuildTarget.Android);
        BuildPipeline.BuildAssetBundle (mainAsset, selectedObjects, abPath + "_i.ab", BuildAssetBundleOptions.CollectDependencies, BuildTarget.iOS);
#else
        BuildPipeline.BuildAssetBundle (mainAsset, selectedObjects, abPath, BuildAssetBundleOptions.CollectDependencies, BuildTarget.StandaloneWindows);
#endif

        List<string> mapping = new List<string> ();
        StringBuilder sb = new StringBuilder ();
        sb.Append (dirName).Append ("=").Append ("[");
        foreach (Object o in selectedObjects) {
            sb.Append (o.name).Append (",");
        }
        sb.Append ("]");
        mapping.Add (sb.ToString ());

        outputMappingFile (mapping);
    }

    [MenuItem ("Assets/Export Models To Assetbundle")]
    public static void ProcessSelectedModel () {
        Object[] selectedObjects = Selection.GetFiltered (typeof (GameObject), SelectionMode.Assets);

        foreach (Object obj in selectedObjects) {
            string path = AssetDatabase.GetAssetPath (obj);
            Debug.Log (path);
            string[] split = path.Replace ("\\", "/").Split ('/');
            string fileName = split[split.Length - 1].Split ('.') [0];
            string extName = split[split.Length - 1].Split ('.') [1];
            if (isModelExtName (extName)) {
                ProcessSingleModel (path, fileName);
            }
        }
    }

    [MenuItem ("Tools/模型工具/导出所有模型")]
    public static void ProcessAllModels () {
        List<string> mapping = new List<string> ();

        string modelPath = "Assets/Models";
        if (!Directory.Exists (modelPath + "/prefabs")) {
            AssetDatabase.CreateFolder (modelPath, "prefabs");
        }
        if (!Directory.Exists (ASSETSBUNDLE_PATH)) {
            Directory.CreateDirectory (ASSETSBUNDLE_PATH);
        }

        string[] assetPath = AssetDatabase.GetAllAssetPaths ();
        List<string> obj2Process = new List<string> ();

        EditorUtility.DisplayProgressBar ("资源打包", "正在扫描Models文件夹", 0);
        foreach (string path in assetPath) {
            EditorUtility.DisplayProgressBar ("资源打包", "正在扫描：" + path, 0);
            if (path.StartsWith (modelPath)) {
                string extName = path.Substring (path.LastIndexOf ('.') + 1, path.Length - path.LastIndexOf ('.') - 1).ToLower ();

                if (isModelExtName (extName)) {
                    obj2Process.Add (path);
                }

            }
        }

        int count = 0;
        foreach (string path in obj2Process) {
            count++;
            EditorUtility.DisplayProgressBar ("资源打包", "正在处理：" + path, (float) count / obj2Process.Count);
            if (path.StartsWith (modelPath)) {
                string[] split = path.Replace ("\\", "/").Split ('/');
                string fileName = split[split.Length - 1].Split ('.') [0];
                EditorUtility.DisplayProgressBar ("资源打包", "正在打包：" + path, (float) count / obj2Process.Count);
                string outputName = fileName;
                ProcessSingleModel (path, outputName);
                mapping.Add (fileName + "=" + "cakepart" + count);

            }
        }
        outputMappingFile (mapping);
        EditorUtility.ClearProgressBar ();

    }

    private static void ProcessSingleModel (string modelPath, string outputName) {
        string[] split = modelPath.Replace ("\\", "/").Split ('/');
        string fileName = split[split.Length - 1].Split ('.') [0];
        string extName = split[split.Length - 1].Split ('.') [1];

        string[] copy = new string[split.Length - 1];
        System.Array.Copy (split, copy, split.Length - 1);
        string filePath = string.Join ("/", copy);

        //Debug.Log(fileName+"."+extName+" from "+filePath);

        if (isModelExtName (extName)) {
            ModelImporter importer = AssetImporter.GetAtPath (modelPath) as ModelImporter;
            importer.globalScale = 15;
            importer.importAnimation = false;
            importer.importMaterials = true;
            importer.SaveAndReimport ();
            //AssetDatabase.

            //texture
            string texturePath = filePath;
            string textureName = fileName;
            if (fileName.ToLower ().StartsWith ("fbx_") || fileName.ToLower ().StartsWith ("obj_")) {
                textureName = fileName.Substring (4);
            }

            texturePath += "/" + textureName + ".png";

            if (AssetDatabase.LoadAssetAtPath<Texture> (texturePath) != null) {
                AssetDatabase.RenameAsset (texturePath, "tex_" + fileName);
                texturePath = filePath + "/tex_" + fileName + ".png";
            } else if (AssetDatabase.LoadAssetAtPath<Texture> (filePath + "/tex_" + textureName + ".png") != null) {
                texturePath = filePath + "/tex_" + textureName + ".png";
            }

            //model
            bool hasPrefix = outputName.ToLower ().StartsWith ("obj_") || outputName.ToLower ().StartsWith ("fbx_");
            if (hasPrefix) {
                outputName = outputName.Substring (4);
            }

            bool needToRename = outputName.ToLower ().Equals (fileName.ToLower ());

            if (needToRename) {
                AssetDatabase.RenameAsset (modelPath, extName + "_" + fileName);
                modelPath = filePath + "/" + extName + "_" + fileName + "." + extName;
            }

            AssetDatabase.SaveAssets ();
            AssetDatabase.Refresh ();

            GameObject go = AssetDatabase.LoadAssetAtPath<GameObject> (modelPath);
            go.transform.localScale = new Vector3 (1, 1, 1);

            List<Renderer> rList = new List<Renderer> ();

            if (go.GetComponent<Renderer> () != null) {
                rList.Add (go.GetComponent<Renderer> ());
            }

            rList.AddRange (go.GetComponentsInChildren<Renderer> ());

            if (rList.Count > 0) {
                foreach (Renderer r in rList) {
                    r.sharedMaterial.shader = Shader.Find ("Mobile/Diffuse Color");
                    r.sharedMaterial.mainTexture = AssetDatabase.LoadAssetAtPath<Texture> (texturePath);
                }
            }

            //GameObject.Instantiate(go,new Vector3(0,0,0),Quaternion.identity);

            if (!Directory.Exists (filePath + "/prefabs")) {
                AssetDatabase.CreateFolder (filePath, "prefabs");
            }

            string prefabPath = filePath + "/prefabs/" + outputName + ".prefab";
            GameObject prefab = PrefabUtility.CreatePrefab (prefabPath, go, ReplacePrefabOptions.ReplaceNameBased);
            BuildPipeline.BuildAssetBundle (prefab, null, ASSETSBUNDLE_PATH + "/" + outputName + "_a.ab", BuildAssetBundleOptions.CollectDependencies, BuildTarget.Android);
            BuildPipeline.BuildAssetBundle (prefab, null, ASSETSBUNDLE_PATH + "/" + outputName + "_i.ab", BuildAssetBundleOptions.CollectDependencies, BuildTarget.iOS);

        }
    }

    private static void outputMappingFile (List<string> mapping) {
        StreamWriter sw = File.AppendText (Application.dataPath + "/abMappinp.txt");
        string[] lines = mapping.ToArray ();
        foreach (string line in lines) {
            sw.WriteLine (line);
        }
        sw.Flush ();
        sw.Close ();
    }

    private static bool isModelExtName (string extName) {
        return extName.ToLower ().Equals ("obj") || extName.ToLower ().Equals ("fbx");
    }

}